﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using KC.Common;
using KC.Common.LogHelper;
using KC.Framework.Base;
using KC.Framework.Tenant;
using KC.Framework.Util;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;

namespace KC.UnitTest
{
    public class TestFixture : IDisposable
    {
        /// <summary>
        /// Local Storage（FTP）、SupplyChainFinance（供应链金融）
        /// </summary>
        public Tenant DbaTenant;
        /// <summary>
        /// Local Storage（Local Disk）、CommercialFactoring（商业保理）
        /// </summary>
        public Tenant TestTenant;
        /// <summary>
        /// Azure Storage、StoreCredit（店铺赊销）
        /// </summary>
        public Tenant BuyTenant;
        /// <summary>
        /// Azure Storage、StoreCredit（店铺赊销）
        /// </summary>
        public Tenant SaleTenant;

        public IServiceCollection Services;

        public ILoggerFactory LoggerFactory;

        public TestFixture()
        {
            //if (ConfigUtil.Config == null)
            //    ConfigUtil.Config = new AppSettingsConfigService();
            if (LogUtil.Logger == null)
                LogUtil.Logger = new NlogLoggingService();
            //if (CacheUtil.Cache == null)
            //{
            //    CacheUtil.Cache = new InMemoryCache();
            //    Service.Core.CacheUtil.Cache = new InMemoryCache();
            //    //CacheUtil.Cache = new RedisCacheService();
            //    //Service.Core.CacheUtil.Cache = new RedisCacheService();
            //}

            var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            environmentName = environmentName??"Dev";
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environmentName}.json", optional: true)
                .AddEnvironmentVariables();

            LogUtil.LogInfo("------Initialze the Environment: " + environmentName);

            var Configuration = builder.Build();

            Services = new ServiceCollection()
                //.AddEntityFrameworkSqlServer()
                .AddDistributedMemoryCache()
                .AddLogging(loggingBuilder =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);

                    loggingBuilder
                       .AddConfiguration(Configuration.GetSection("Logging"))
                       .AddFilter("Microsoft", LogLevel.Debug)
                       .AddFilter("System", LogLevel.Debug)
                       .AddFilter("KC.UnitTest.TestFixture", LogLevel.Debug)
                       .AddConsole()
                       .AddDebug()
                       .AddNLog(Configuration);
                });

            LoggerFactory = Services.BuildServiceProvider().GetService<ILoggerFactory>();

            Services.AddHttpClient();

            #region 配置文件的读取及静态类GlobalConfig的设置
            Framework.Base.GlobalConfig.InitGlobalConfig(Configuration);

            try
            {
                using (var scope = Services.BuildServiceProvider().CreateScope())
                {
                    var clientFactory = scope.ServiceProvider.GetService<System.Net.Http.IHttpClientFactory>();
                    var url = GlobalConfig.SSOWebDomain + "api/GlobalConfigApi/GetData";
                    var client = clientFactory.CreateClient();
                    client.BaseAddress = new Uri(GlobalConfig.SSOWebDomain);
                    // for fiddler proxy setting
                    //var httpClientHandler = new HttpClientHandler
                    //{
                    //    // Does not work 
                    //    Proxy = new WebProxy("http://Kent-pc:8888", false),
                    //    UseProxy = true
                    //};

                    var response = client.GetAsync(url).Result;
                    if (response == null)
                        return;
                    var responseString = response.Content.ReadAsStringAsync().Result;
                    if (string.IsNullOrEmpty(responseString))
                        return;
                    var globalConfigData = SerializeHelper.FromJson<GlobalConfigData>(responseString);
                    if (globalConfigData == null)
                        return;
                    GlobalConfig.InitGlobalConfigWithApiData(Configuration, globalConfigData);
                }
            }
            catch(Exception ex)
            {
                var logger = LoggerFactory.CreateLogger<TestFixture>();
                logger.LogError(ex.Message, ex);
            }

            #endregion

            DbaTenant = TenantConstant.DbaTenantApiAccessInfo;
            TestTenant = TenantConstant.TestTenantApiAccessInfo;
            BuyTenant = TenantConstant.BuyTenantApiAccessInfo;
            SaleTenant = TenantConstant.SaleTenantApiAccessInfo;

        }
        public void Dispose()
        {
            // Do "global" teardown here; Only called once.
        }
    }

    public abstract class TestBase : Xunit.IClassFixture<TestFixture>
    {
        /// <summary>
        /// Local Storage（FTP）、SupplyChainFinance（供应链金融）
        /// </summary>
        public Tenant DbaTenant;
        /// <summary>
        /// Local Storage（Local Disk）、CommercialFactoring（商业保理）
        /// </summary>
        public Tenant TestTenant;
        /// <summary>
        /// Azure Storage、StoreCredit（店铺赊销）
        /// </summary>
        public Tenant BuyTenant;
        /// <summary>
        /// Azure Storage、StoreCredit（店铺赊销）
        /// </summary>
        public Tenant SaleTenant;

        public IServiceCollection Services;

        public ILoggerFactory LoggerFactory;

        public TestBase(TestFixture data)
        {
            DbaTenant = data.DbaTenant;
            TestTenant = data.TestTenant;
            BuyTenant = data.BuyTenant;
            SaleTenant = data.SaleTenant;

            Services = data.Services;

            LoggerFactory = data.LoggerFactory;

            Initialize();
        }

        protected virtual void InjectTenant(Tenant tenant)
        {
            Services.AddTransient(serviceProvider =>
            {
                switch (tenant.TenantName)
                {
                    case TenantConstant.DbaTenantName:
                        return DbaTenant;
                    case TenantConstant.SaleTenantName:
                        return SaleTenant;
                    case TenantConstant.BuyTenantName:
                        return BuyTenant;
                    default:
                        return TestTenant;
                }
            });
        }

        protected virtual void Initialize()
        {
        }

        protected virtual void Cleanup()
        {
        }


        public string ToAssertableString(IDictionary<string, List<int>> dictionary)
        {
            var pairStrings = dictionary.OrderBy(p => p.Key)
                                        .Select(p => p.Key + ": " + string.Join(", ", p.Value));
            return string.Join("; ", pairStrings);
        }
        public string ToAssertableString(IDictionary<string, List<string>> dictionary)
        {
            var pairStrings = dictionary.OrderBy(p => p.Key)
                                        .Select(p => p.Key + ": " + string.Join(", ", p.Value));
            return string.Join("; ", pairStrings);
        }
    }
}
